#include <stdio.h>
#include <stdlib.h>
#include "platform.h"
#include "xparameters.h"

#include "xguessspot.h"

struct Point {
	int ship;
	int guess;
	int hit;
};

struct Board {
	struct Point line[10];
	int hitCount;

};

int board_isSunk(struct Board *b) {
	if (b->hitCount == 3)
		return 1;
	else
		return 0;
}

void point_placeShip(struct Point *p) {
	struct Point *temp = p;
	temp->ship = 1;
	*p = *temp;
}

int point_hasShip(struct Point *p) {
	return p->ship;
}

void Board_setLocation(struct Board *b, int left, int right) {
	int i;
	for (i = left; i <= right; i++) {
		struct Point *q = &(b->line[i]);
		point_placeShip(q);
	}
}

void Board_initializeBoard(struct Board *b) {
	struct Board *temp = b;
	int a;
	for (a = 0; a < 10; a++) {
		struct Point *q = &(temp->line[a]);
		q->guess = 0;
		q->ship = 0;
		q->hit = 0;
		temp->line[a] = *q;
	}
	temp->hitCount = 0;
	*b = *temp;
}

int beenGuessed(struct Board *b, int guessIndex) {
	if (b->line[guessIndex].guess == 1)
		return 1;
	else
		return 0;
}

void board_hitChecker(struct Board *b, int guessIndex)
{
	// Vivado HLS generates
		int status;
		// Create guessspot_0 pointer
		XGuessspot do_guessSpot;
		XGuessspot_Config *do_guessspot_cfg;
		do_guessspot_cfg = XGuessspot_LookupConfig(XPAR_GUESSSPOT_0_DEVICE_ID);

		if (!do_guessspot_cfg) {
			xil_printf("Error loading configuration for do_guessspot_0_cfg \n\r");
		}

		status = XGuessspot_CfgInitialize(&do_guessSpot, do_guessspot_cfg);
		if (status != XST_SUCCESS) {
			xil_printf("Error initializing for do_guessspot_0 \n\r");
		}

		XGuessspot_Initialize(&do_guessSpot, XPAR_GUESSSPOT_0_DEVICE_ID); // this is optional in this case


	int hitCheck = b->line[guessIndex].ship;
	XGuessspot_Set_guessIndex(&do_guessSpot, (u32)hitCheck);
	XGuessspot_Start(&do_guessSpot);
	while (!XGuessspot_IsDone(&do_guessSpot));
	int check = XGuessspot_Get_return(&do_guessSpot);

	if(check == 1)
	{
		xil_printf("HIT!\n\r");
		b->hitCount++;
	}
	else
		xil_printf("Miss!\n\r");
	b->line[guessIndex].guess = 1;
}

int main()
{
	init_platform();

	//Create two boards
	struct Board playerBoard, compBoard;
	Board_initializeBoard(&playerBoard);
	Board_initializeBoard(&compBoard);

	//Get index for player ship
	int frontIndex = 8;
	while(frontIndex > 7 || frontIndex < 0)
	{
		xil_printf("At what index do you want to place the front of your ship? \n\r");
		scanf("%d",&frontIndex);
		if(frontIndex > 7 || frontIndex < 0)
		{
			xil_printf("Index must be between 0 and 7! \n\r");
		}
		else
			break;
	}
	//xil_printf("Index received!  %d\n\r",frontIndex);

	//Place player ship
	Board_setLocation(&playerBoard, frontIndex, frontIndex+2);
	xil_printf("Ship placed! \n\r");

	//Generate random index for computer ship and place computer ship
	int compIndex = (rand() % 10);
	while(compIndex > 7 || compIndex < 0)
	{
		compIndex = (rand() % 10);
	}
	Board_setLocation(&compBoard, compIndex, compIndex+2);
	//xil_printf("My ship placed at index %d\n\r", compIndex);
	int count = 0;
	int array[10];
	for(int i = 0; i < 10; i++)
	{
		array[i] = i;
	}

	for(int i = 0; i <10; i++)
	{
		int temp = array[i];
		int randIndex = rand() % 10;
		array[i] = array[randIndex];
		array[randIndex] = temp;
	}

	while(1)
	{
		//Get player guess for computer ship
		xil_printf("Guess where my ship is! \n\r");
		int guessIndex;
		scanf("%d",&guessIndex);
		int guessReturn = beenGuessed(&compBoard, guessIndex);

		//Make sure index hasn't been guessed and is in range
		while(guessIndex < 0 || guessIndex > 9 || guessReturn)
		{
			if(guessIndex < 0 || guessIndex > 9)
			{
				xil_printf("You must guess an index between 0 and 9! Guess again! \n\r");
				scanf("%d",&guessIndex);
				guessReturn = beenGuessed(&compBoard, guessIndex);
			}
			else
			{
				xil_printf("You've already guessed that spot! Guess again! \n\r");
				scanf("%d",&guessIndex);
				guessReturn = beenGuessed(&compBoard, guessIndex);
			}
		}
		xil_printf("You guessed %d!\n\r",guessIndex);

		//Determine if a ship is at the guessed index
		board_hitChecker(&compBoard, guessIndex);

		//Check if the ship is sunk
		if(board_isSunk(&compBoard))
		{
			xil_printf("Ship sunk! You win! \n\r");
			exit(0);
		}

		xil_printf("My turn! \n\r");

		//Generate random number for computer to guess

		int compGuess = array[count];
		xil_printf("I guess %d!\n\r",compGuess);

		//Determine if ship is at guessed index
		board_hitChecker(&playerBoard, compGuess);
		//Check if the ship is sunk
		if(board_isSunk(&playerBoard))
		{
			xil_printf("Ship sunk! I win! \n\r");
			exit(0);
		}

		xil_printf("Your turn! \n\r");
		count++;
    }
	cleanup_platform();
	return 0;
}
